<?php

declare(strict_types=1);

namespace app\command\model;

use app\eslib\FileUtils;
use app\model\admin\EsxdmSysCrontabModel;
use Cron\CronExpression;
use think\facade\Db;

class CronTaskModel{
    
    public $logDir = '';
    public $lastExecFile = '';
    public $lastExecSuccessFile = '';

    // 常用时间方案
    // 1分钟1次 * * * * *
    // 10分钟1次 */10 * * * *
    // 每天早上3点 0 3 * * *
    public function run($isTest = false)
    {
        self::task1($isTest);
        self::task2($isTest);
        self::task3($isTest);
        $expression = '*/10 * * * *';
        if ($isTest) {
            $expression = '* * * * *';
        }
        // 每分钟执行执行一次
        $cron = new CronExpression($expression);
        if (!$cron->isDue()) {
            return;
        }
        $dateToday = date('Y-m-d');
        echo '更新今天的统计数据', PHP_EOL;
    }
    // 每天 00:00 更新昨天的统计
    public function task1($isTest)
    {
        // 每天00:00执行一次
        $expression = '0 0 * * *';
        if ($isTest) {
            $expression = '* * * * *';
        }
        $cron = new CronExpression($expression);
        if (!$cron->isDue()) {
            return;
        }
        $dateYesterday = date('Y-m-d', strtotime('-1 day'));
        echo '更新昨天的统计数据', PHP_EOL;
    }
    // 每10分钟自动开盲盒
    // 服务器设定时间，最好是后台可以改这个时间，默认每5分钟执行一次策略，策略有2个
    // 1、生成用户、去随机开盲盒
    // 2、从老用户里抽用户去开盲盒
    // 逻辑1
    // 生成用户，通过头像接口和名称接口生成一个用户，存数据库，并与正常用户做区分
    // 生成用户的时候，随机给用户20-1000元的金额
    // 新生成的用户去开盲盒，第一次100%开新手礼盒即ID为7的那个盲盒的奖品，从现有的组里随机抽一组，抽一个没开的盲盒，开起来，要生成开盒记录，如果中了大奖也要公告，第二次起，就随机所有盲盒取一个盲盒去开，开到账户没钱为止，账户低于15元的号就不取了，要记录这些号开的盲盒数量，后续将作为重新启用某一些号的依据
    // 逻辑2
    // 从生成的用户里抽一个用户去开盲盒，随机抽盲盒，随机选格子开，遇到账户低于15元的号不抽。
    // 如果随机到逻辑2，但是没老用户了，就执行逻辑1
    public function task2($isTest)
    {
        $minute = rand(3, 10);
        $expression = '*/10 * * * *';
        if ($isTest) {
            $expression = '* * * * *';
        }
        $cron = new CronExpression($expression);
        if (!$cron->isDue()) {
            return;
        }
        $task = EsxdmSysCrontabModel::where('id', 1)->find();
        if ($task && $task->status == 0) {
            echo '任务暂停', PHP_EOL;
            return;
        }
        echo '任务继续', PHP_EOL;
    }
    public function task3($isTest)
    {
        $expression = '*/5 * * * *';
        if ($isTest) {
            $expression = '* * * * *';
        }
        $cron = new CronExpression($expression);
        if (!$cron->isDue()) {
            return;
        }
        $sqls = [
            'update esxdm_applaunch_log l inner join usr_user u on l.oaid=u.oaid set l.user_id=u.id where l.user_id=0 and l.oaid <> \'\';',
            'update esxdm_applaunch_log l inner join usr_user u on l.android_id=u.android_id set l.user_id=u.id where l.user_id=0 and l.android_id <> \'\';'
        ];
        foreach ($sqls as $sql) {
            Db::execute($sql);
        }
    }
    public function init()
    {
        $logDir = runtime_path() . 'autotask/';
        if (!is_dir($logDir)) {
            @mkdir($logDir, 0777, true);
        }
        $this->logDir = $logDir;
        $this->lastExecFile = $logDir . 'last_exec.txt';
        $this->lastExecSuccessFile = $logDir . 'last_exec_success.txt';
    }
    public function showStatus()
    {
        echo '当前运行状态：', ($this->checkStop() ? '已停止' : '已启动'), PHP_EOL;
        if (file_exists($this->lastExecFile)) {
            echo '上次运行时间：', file_get_contents($this->lastExecFile), PHP_EOL;
        }
        if (file_exists($this->lastExecSuccessFile)) {
            echo '上次成功执行时间：', file_get_contents($this->lastExecSuccessFile), PHP_EOL;
        }
    }
    public function stopTask()
    {
        file_put_contents($this->logDir . 'stop.txt', date('Y-m-d H:i:s'));
    }
    public function startTask()
    {
        unlink($this->logDir . 'stop.txt');
    }
    public function checkStop()
    {
        // 如果存在文件 runtime/autotask/stop.txt 则判定手动停止任务
        return file_exists($this->logDir . 'stop.txt');
    }

    // 记录执行日志（每年每时循环覆盖）
    public function writeLog($msg, $filename = '')
    {
        if (!$filename) {
            $filename = date('H') . '.log';
        }
        $filename = $this->logDir . date('md') . '/' . $filename; // runtime/autotask/0830/15.log
        $dir = dirname($filename);
        if (!is_dir($dir)) {
            @mkdir($dir, 0777, true);
        }
        if (is_array($msg)) {
            $msg = self::varExport($msg);
        }
        $msg = date('Y-m-d H:i:s') . PHP_EOL . $msg . PHP_EOL;
        file_put_contents($filename, $msg, FILE_APPEND);
    }
    public function clearLog()
    {
        $fileIter = new \FileSystemIterator($this->logDir);
        foreach ($fileIter as $fileInfo) {
            if ($fileInfo->isDir()) {
                $path = $this->logDir . $fileInfo->getFilename();
                FileUtils::rmdir($path, true);
                echo '删除目录：', $path, PHP_EOL;
            }
        }
        echo '删除日志文件完成', PHP_EOL;
    }
    public function showLogs()
    {
        $i = 0;
        $fileIter = new \FileSystemIterator($this->logDir);
        foreach ($fileIter as $fileInfo) {
            if ($fileInfo->isDir()) {
                $path = $this->logDir . $fileInfo->getFilename();
                $fileIter2 = new \FilesystemIterator($path);
                foreach ($fileIter2 as $fileInfo2) {
                    echo '日志文件：', $fileInfo->getFilename(), '/', $fileInfo2->getFilename(), PHP_EOL;
                    $i++;
                }
            }
        }
        echo '共 ', $i, ' 个日志文件', PHP_EOL;
    }
    public function showLog($filename)
    {
        echo '日志文件：', $filename, PHP_EOL;
        $path = $this->logDir . $filename;
        if (!file_exists($path)) {
            echo '日志文件不存在：', $path, PHP_EOL;
        }
        echo file_get_contents($path);
    }
    /**
     * var_export() 方法的现代风格版
     * 说明：原始版：array()， 现代版：[]
     * @param mixed $var
     * @param string $indent 缩进内容，默认是空格
     * @param boolean $isCompact 是否紧凑模式，即数组是否换行
     * @return string
     */
    public function varExport($var, $indent = '', $isCompact = false)
    {
        switch (gettype($var)) {
            case "string":
                return '\'' . addcslashes($var, "\\\$\"\r\n\t\v\f") . '\'';
            case "array":
                if (count($var) == 0) {
                    return '[]';
                }
                $newLine = $isCompact ? '' : "\n";
                $itemSpace = $isCompact ? "$indent " : "$indent    ";
                $indexed = array_keys($var) === range(0, count($var) - 1);
                $r = [];
                foreach ($var as $key => $value) {
                    $r[] = $itemSpace . ($indexed ? "" : self::varExport($key) . " => ") . self::varExport($value, $itemSpace);
                }
                return "[$newLine" . implode(",$newLine", $r) . "$newLine" . $indent . "]";
            case "boolean":
                return $var ? "TRUE" : "FALSE";
            default:
                return var_export($var, true);
        }
    }
}